package dht.tool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
import java.util.Vector;

import dht.entity.GlobalVariables;

public class FSImageGenerator {

	public static void create(int ringLength, String fileName,
			Vector<String> servers) {
		HashMap<Integer, HashSet<String>> vnodeId2ServerIds = new HashMap<Integer, HashSet<String>>();
		for (int i = 0; i < ringLength; ++i) {
			vnodeId2ServerIds.put(i, new HashSet<String>());
			vnodeId2ServerIds.get(i).add(servers.get(i % servers.size()));
		}
		try {
			FileOutputStream fos = new FileOutputStream(fileName);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(vnodeId2ServerIds);
			oos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static HashMap<Integer, HashSet<String>> createRandom(
			int ringLength, int replicaLevel, String fileName,
			Vector<String> servers) {
		HashMap<Integer, HashSet<String>> vnodeId2ServerIds = new HashMap<Integer, HashSet<String>>();
		Random ran = new Random(GlobalVariables.seed);
		for (int i = 0; i < ringLength; ++i) {
			vnodeId2ServerIds.put(i, new HashSet<String>());
			HashSet<Integer> used = new HashSet<Integer>();
			for (int j = 0; j < Math.min(replicaLevel, servers.size()); ++j) {
				while (true) {
					int idx = ran.nextInt(servers.size());
					if (!used.contains(idx)) {
						vnodeId2ServerIds.get(i).add(servers.get(idx));
						used.add(idx);
						break;
					}
				}
			}
		}
		try {
			FileOutputStream fos = new FileOutputStream(fileName);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(vnodeId2ServerIds);
			oos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return vnodeId2ServerIds;
	}

	public static void main(String[] args) throws Exception {
		GlobalVariables.initialize(args[0]);
		Scanner cin = new Scanner(new File(GlobalVariables.slavesFile));
		Vector<String> serverIds = new Vector<String>();
		int port = GlobalVariables.localPort;
		while (cin.hasNext()) {
			String serverId = InetAddress.getByName(cin.next()) + ":" + port;
			serverIds.add(serverId);
			System.out.println("serverId: " + serverId);
		}
		FSImageGenerator.createRandom(GlobalVariables.ringLength,
				GlobalVariables.replicaLevel, GlobalVariables.fsImage,
				serverIds);
	}
}
